#ifndef DBSTORAGE_DBSTORAGE_FACTORY
#define DBSTORAGE_DBSTORAGE_FACTORY

#include "DbStorage/DbStorageConfig.hpp"
#include "Storage/StorageFactory.hpp"

namespace CaseDB { class Connection; }

namespace DbStorage
{

class ProjectDbStorage;
class PackageDbStorage;
class RequirementsDbStorage;

/// @ingroup DbStorage
/// @brief It provides access to various database storages, specialized on different storage entities.
class DBSTORAGE_API DbStorageFactory: public Storage::StorageFactory
{
	DbStorageFactory( const DbStorageFactory& );
	DbStorageFactory& operator=( const DbStorageFactory& );

public:
	/// @brief It initializes the factory.
	/// @param pDbConnection the database connection to be used by the provided storages.
	///
	/// It builds the storages for each entity from the beginning. The factory methods for each type of storage will 
	///	provide references to these built storages.
	DbStorageFactory( CaseDB::Connection* pDbConnection);

	/// @brief It destroys the owned specialized storages.
	virtual ~DbStorageFactory();

	/// @sa Storage::StorageFactory::getProjectStorage()
	virtual Storage::ProjectStorage& getProjectStorage();
	
	/// @sa Storage::StorageFactory::getPackageStorage()
	virtual Storage::PackageStorage& getPackageStorage();

	/// @sa Storage::StorageFactory::getRequirementStorage()
	virtual Storage::RequirementsStorage& getRequirementStorage();

	/// @sa Storage::createProjectCreationCommand( Model::Project& subject);
	virtual Storage::StorageCommand* createProjectCreationCommand( Model::Project& subject);
	
	/// @sa Storage::createPackageCreationCommand( Model::Package& subject);
	virtual Storage::StorageCommand* createPackageCreationCommand( Model::Package& subject);

	/// @sa Storage::StorageFactory::createPackageRemovalCommand( Model::Package&)
	virtual Storage::StorageCommand* createPackageRemovalCommand( Model::Package& subject);

	/// @sa Storage::createRequirementCreationCommand( Model::Requirement&)
	virtual Storage::StorageCommand* createRootRequirementCreationCommand( Model::Requirement& subject);

	/// /// @sa Storage::createRequirementRemovalCommand( Model::Requirement& subject)
	virtual Storage::StorageCommand* createRootRequirementRemovalCommand( Model::Requirement& subject, Model::Package* pParentPackage);

	/// @brief It gets the used database connection
	/// @{
	CaseDB::Connection& dbConnection() { return *pDbConnection_; }
	const CaseDB::Connection& dbConnection() const { return *pDbConnection_; }
	/// @}

private:
	ProjectDbStorage* pProjectStorage_;
	PackageDbStorage* pPackageStorage_;
	RequirementsDbStorage* pRequirementStorage_;

	CaseDB::Connection* pDbConnection_;
};
	
} // namespace DbStorage

#endif // DBSTORAGE_DBSTORAGE_FACTORY